#ifndef DICTIONARY_NODE_H
#define DICTIONARY_NODE_H

#include <map>

#include "Types.h"
#include "Section.h"

#include <string>

namespace Dictionary
{
	template <typename T = std::string>
	class Node
	{
	 public:
		   typedef std::map<SectionType, Section<T> * > unique_sections_t;

		   Node() : id(-1) {}
		   Node(long id) : id(id) {}
		  ~Node() 
			 {
				 std::for_each(sections.begin(),sections.end(),DeleteMapContainerContent<unique_sections_t::value_type>());
			 }
			 void set_id(long id);
			 void set_term(const std::string &term) { this->term = term; }
			 bool add_section(Section<T> *section);
			 void set_total_term_frequency(long term_freq) { total_term_frequency = term_freq; }

			 long get_id() const;
			 long get_total_term_frequency() const { return this->total_term_frequency; }
			 const std::string &get_term() const { return term; }
			 const unique_sections_t * get_sections() const;
			 const Section<T> * get_section_by_type(SectionType section_type) const;

			 bool operator== (const Node &) const;
			 bool operator!= (const Node &) const;

	 private:
			long id;
			std::string term;
			long total_term_frequency;
			unique_sections_t sections;

			struct SectionTypeResolver : std::unary_function<Section<T> * ,bool>
			{
				SectionTypeResolver(SectionType section_type) : section_type(section_type) {}

				bool operator()(Section<T> *section) { return section->get_section_type() == section_type; }

				SectionType section_type;
			};
	};
}
template <typename T>
inline void Dictionary::Node<T>::set_id(long id) { this->id = id; }
template <typename T>
inline long Dictionary::Node<T>::get_id() const { return this->id; }
template <typename T>
inline bool Dictionary::Node<T>::operator==(const Dictionary::Node<T> &node) const { return this->id == node.id; }
template <typename T>
inline bool Dictionary::Node<T>::operator!=(const Dictionary::Node<T> &node) const { return !this->operator==(node); }

template <typename T>
bool Dictionary::Node<T>::add_section(Dictionary::Section<T> *section)
{
	if (sections.count(section->get_section_type())) return false;
	sections.insert(std::make_pair(section->get_section_type(),section));
	return true;
}

template <typename T>
const typename Dictionary::Node<T>::unique_sections_t * Dictionary::Node<T>::get_sections() const { return &sections; }

template <typename T> const
Dictionary::Section<T> * Dictionary::Node<T>::get_section_by_type(SectionType section_type) const
{
	unique_sections_t::iterator i = sections.find(section_type), i_end = sections.end();
	if (i == i_end) return 0;

	return (*i).second;
}

#endif